import 'dart:convert';
import 'package:connectivity/connectivity.dart';
import 'package:dio/dio.dart';
import 'package:flutter_application_1/global.dart';
import 'package:flutter_application_1/models/JsonConvert.dart';
import 'package:flutter_application_1/utils/auth.dart';

/// 返回结果编码
class Code {
  // 请求成功
  static const int SUCCESS = 200;
  // 普通错误
  static const int COMMON_ERROR = 1;
  // 权限错误
  static const int AUTH_ERROR = 2;
}

/// 调用方法
class Method {
  static const GET = 'GET';

  static const POST = 'POST';
}

/// 接口返回结果格式
class ResultData<T> {
  ResultData({
    this.code,
    this.msg,
    this.data,
  });

  factory ResultData.fromJson(Map<String, dynamic> jsonRes) => ResultData<T>(
        code: JsonConvert.asT<int?>(jsonRes['code']),
        msg: JsonConvert.asT<String?>(jsonRes['msg']),
        data: JsonConvert.asT<dynamic?>(jsonRes['data']),
      );

  int? code;
  String? msg;
  T? data;

  @override
  String toString() {
    return jsonEncode(this);
  }

  Map<String, dynamic> toJson() => <String, dynamic>{
        'code': code,
        'msg': msg,
        'data': data,
      };

  ResultData clone() => ResultData.fromJson(
      JsonConvert.asT<Map<String, dynamic>>(jsonDecode(jsonEncode(this)))!);
}

class ContentTypes {
  static const String JSON = 'application/json;charset=UTF-8';

  static const String Form = 'application/x-www-form-urlencoded;charset=UTF-8';
}

/// 请求类
/// dio文档：https://github.com/flutterchina/dio/blob/master/README-ZH.md
class Request {
  // token 请求头命名
  static const String TOKENKEY = 'Authorization';
  // 超时时间
  static const int TIMEOUT = 8000;

  // dio 实例
  late Dio dio;
  // 接口地址
  String baseUrl;
  // 自定义请求头
  Map<String, dynamic> headers;
  // 数据格式
  String contentType;

  Request({
    this.baseUrl = Global.BASE_URL,
    this.headers = const {},
    this.contentType = ContentTypes.JSON,
  }) {
    this.dio = Dio();

    this.dio.interceptors.add(
          InterceptorsWrapper(
            onRequest:
                (RequestOptions options, RequestInterceptorHandler handler) {
              // 接口地址
              options.baseUrl = this.baseUrl;
              // 超时时间
              options.connectTimeout = TIMEOUT;

              // print('\n请求：' + options.path);
              // print('----------------------------------------------');
              // print('| query：' + options.queryParameters.toString());
              // print('| data：' + options.data.toString());
              // print('');

              handler.next(options);
            },
            onResponse: (Response<dynamic> response,
                ResponseInterceptorHandler handler) {
              print(
                  '================================================================================');
              print('响应：' + response.requestOptions.path);
              print(
                  '================================================================================');
              print('| query：' +
                  response.requestOptions.queryParameters.toString());
              print('| data：' + response.requestOptions.data.toString());
              print('| header：' + response.requestOptions.headers.toString());
              print('| response：' + response.data.toString());
              print(
                  '================================================================================');

              handler.next(response);
            },
            onError: (DioError err, ErrorInterceptorHandler handler) {
              // print('网络请求错误:');
              // print(err);
              handler.next(err);
            },
          ),
        );
  }

  // 获取请求头
  Map<String, dynamic>? getHeader() {
    final Map<String, dynamic> defaultHeader = {
      TOKENKEY.toLowerCase(): getToken(),
      'Content-Type': this.contentType,
    };
    // 合并自定义请求头
    defaultHeader.addAll(this.headers);
    return defaultHeader;
  }

  // 根据泛型 T 转换成实例对象
  ResultData<T> fromJsonAsT<T>(Map<String, dynamic> responseData) {
    responseData = responseData;
    responseData['data'] =
        JsonConvert.fromJsonAsT<T>(responseData['data'] ?? {});
    ResultData<T> resultData = ResultData<T>.fromJson(responseData);
    return resultData;
  }

  // 处理错误
  ResultData<T> onError<T>(Object e) {
    DioError err = e as DioError;

    return ResultData<T>(
      code: err.response?.statusCode ?? Code.COMMON_ERROR,
      msg: err.message.toString(),
    );
  }

  Future<ResultData<T>> request<T>({
    required String url,
    required String method,
    Map<String, dynamic>? data,
  }) async {
    // 检查网络
    if (await (new Connectivity().checkConnectivity()) ==
        ConnectivityResult.none) {
      return ResultData<T>(
        code: Code.COMMON_ERROR,
        msg: '网络连接不可用',
      );
    }

    Options? options = Options(
      headers: this.getHeader(),
    );
    try {
      // 设置请求方法
      options.method = method;

      Response response = await dio.request(
        url,
        queryParameters: method == Method.GET ? data : null,
        data: method == Method.POST ? data : null,
        options: options,
      );

      return this.fromJsonAsT<T>(response.data);
    } catch (e) {
      return this.onError(e);
    }
  }

  // get
  Future<ResultData<T>> get<T>({
    required String url,
    Map<String, dynamic>? data,
  }) {
    return this.request(
      url: url,
      method: Method.GET,
      data: data,
    );
  }

  // post
  Future<ResultData<T>> post<T>({
    required String url,
    Map<String, dynamic>? data,
  }) {
    return this.request(
      url: url,
      method: Method.POST,
      data: data,
    );
  }
}
